package com.dollkey.packagemanager;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.Signature;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;

import com.zhy.adapter.recyclerview.CommonAdapter;
import com.zhy.adapter.recyclerview.base.ViewHolder;
import com.zhy.adapter.recyclerview.wrapper.EmptyWrapper;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements FilterEditWindow.INameChangeListener {
    private static final String TAG = "MainActivity";
    private FilterEditWindow mFilterEditWindow;
    private EmptyWrapper mAdapter;
    private List<PackageInfo> mList;
    private SharedPreferences mSharedPreferences;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mSharedPreferences = getSharedPreferences("config", Context.MODE_PRIVATE);
        RecyclerView recyclerView = findViewById(R.id.recycler_view);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
        mList = new ArrayList<>();
        mAdapter = new EmptyWrapper(new CommonAdapter<PackageInfo>(this, R.layout.item_package, mList) {
            @Override
            protected void convert(ViewHolder holder, PackageInfo packageInfo, int position) {
                holder.setText(R.id.text, packageInfo.packageName);
                holder.setText(R.id.version_name, packageInfo.versionName);
                if (packageInfo.signatures != null)
                    holder.setText(R.id.md5, packageInfo.signatures[0].toCharsString());
                else
                    holder.setText(R.id.md5, String.valueOf(packageInfo.applicationInfo.uid));
                holder.setText(R.id.name, packageInfo.applicationInfo.loadLabel(getPackageManager()).toString());
                holder.setImageDrawable(R.id.icon_iv, packageInfo.applicationInfo.loadIcon(getPackageManager()));
                holder.setVisible(R.id.is_system, (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0);

                holder.itemView.setOnLongClickListener(v -> {
                    getSign(packageInfo.packageName);
//                    Intent intent = getAppOpenIntentByPackageName(mContext, packageInfo.packageName);
//                    if (intent != null) {
////                    Intent intent = new Intent();
////                    intent.setAction("com.android.mobileviewer.HtmlService");
////                    intent.setPackage("com.android.mobileviewer");
//                        startActivity(intent);
//                        Toast.makeText(mContext, "启动成功", Toast.LENGTH_SHORT).show();
//                    } else {
//
//                        Toast.makeText(mContext, "没有获取到intent", Toast.LENGTH_SHORT).show();
//                    }
                    return false;
                });
            }
        });
        mAdapter.setEmptyView(R.layout.view_empty);
        recyclerView.setAdapter(mAdapter);
        setList();
    }

    private void setList() {
        mList.clear();
        String filterStr = mSharedPreferences.getString("filterString", "");
        boolean isFilter = mSharedPreferences.getBoolean("isFilter", true);
        String[] filters = {};
        boolean hasFilter = filterStr != null && !filterStr.trim().equals("");
        if (hasFilter) {
            filters = filterStr.replace(",", "\n").replace("，", "\n")
                    .replace("\r\n", "\n").split("\n");
        }
        List<PackageInfo> packageInfos = getPackageManager().getInstalledPackages(0);
        for (PackageInfo packageInfo : packageInfos) {
            boolean isAdd;
            if (hasFilter) {
                isAdd = isFilter(filters, packageInfo) && (!isFilter || (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0);
            } else {
                isAdd = !isFilter || (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0;
            }
            if (isAdd) {
                mList.add(packageInfo);
            }
        }
        mAdapter.notifyDataSetChanged();
    }

    private boolean isFilter(String[] filters, PackageInfo packageInfo) {
        for (String filter : filters)
            if (filter != null && !filter.trim().equals("") &&
                    (packageInfo.packageName.contains(filter) ||
                            packageInfo.applicationInfo.loadLabel(getPackageManager()).toString().contains(filter)))
                return true;
        return false;
    }

    //重写onCreateOptionMenu(Menu menu)方法，当菜单第一次被加载时调用
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        //填充选项菜单（读取XML文件、解析、加载到Menu组件上）
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    // 让菜单同时显示图标和文字
    @Override
    public boolean onMenuOpened(int featureId, Menu menu) {
        if (menu != null) {
            if (menu.getClass().getSimpleName().equalsIgnoreCase("MenuBuilder")) {
                try {
                    @SuppressLint("PrivateApi") Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
                    method.setAccessible(true);
                    method.invoke(menu, true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return super.onMenuOpened(featureId, menu);
    }

    //重写OptionsItemSelected(MenuItem item)来响应菜单项(MenuItem)的点击事件（根据id来区分是哪个item）
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        switch (item.getItemId()) {
            case R.id.start:
                if (mFilterEditWindow == null) {
                    mFilterEditWindow = new FilterEditWindow(this, null, this);
                }
                mFilterEditWindow.setText(mSharedPreferences.getString("filterString", ""))
                        .setFilter(mSharedPreferences.getBoolean("isFilter", true)).showAtCenter();
                break;
            case R.id.file:
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
                } else {
                    openFileSelect();
                }
                break;
            default:
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    private void openFileSelect() {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        //intent.setType(“image/*”);//选择图片
        //intent.setType(“audio/*”); //选择音频
        //intent.setType(“video/*”); //选择视频 （mp4 3gp 是android支持的视频格式）
        //intent.setType(“video/*;image/*”);//同时选择视频和图片
        //intent.setType("*/*");//无类型限制
        intent.setType("application/vnd.android.package-archive");//选择apk
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        startActivityForResult(intent, 1);
    }

    /**
     * 权限申请返回结果
     *
     * @param requestCode  请求码
     * @param permissions  权限数组
     * @param grantResults 申请结果数组，里面都是int类型的数
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { //同意权限申请
                    openFileSelect();
                } else { //拒绝权限申请
                    Toast.makeText(this, "没用获取到权限", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
                break;
        }
    }

    @Override
    public void confirm(String name, boolean isFilter) {
        mSharedPreferences.edit().putString("filterString", name).putBoolean("isFilter", isFilter).apply();
        setList();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {
            Uri uri = data.getData();
            String path;
            if (uri != null && "file".equalsIgnoreCase(uri.getScheme())) {//使用第三方应用打开
                path = uri.getPath();
            } else {
                path = FileSelectUtil.getPath(this, uri);
            }
//            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {//4.4以后
//                path = getPath(this, uri);
//                Toast.makeText(this, path, Toast.LENGTH_SHORT).show();
//            } else {//4.4以下下系统调用方法
//                path = getRealPathFromURI(uri);
//                Toast.makeText(MainActivity.this, path + "222222", Toast.LENGTH_SHORT).show();
//            }
            Log.e("MainActivity", "path:" + path);
            if (path != null && path.contains(".apk")) {
                PackageManager pm = getPackageManager();
                PackageInfo info = pm.getPackageArchiveInfo(path, 0);
                Log.e("MainActivity", "info_" + (info == null));
                if (info != null) {
                    ApplicationInfo appInfo = info.applicationInfo;
                    appInfo.sourceDir = path;
                    appInfo.publicSourceDir = path;
                    AlertDialog.Builder builder = new AlertDialog.Builder(this);
                    try {
                        builder.setIcon(appInfo.loadIcon(pm));
                    } catch (OutOfMemoryError e) {
                        builder.setIcon(R.mipmap.ic_launcher);
                        Log.e("ApkIconLoader", e.toString());
                    }
                    Log.e("MainActivity", appInfo.loadLabel(getPackageManager()).toString());
                    builder.setTitle(appInfo.loadLabel(getPackageManager()).toString());
                    String msg = "包名：\n".concat(info.packageName).concat("\n版本号：\n").concat(info.versionName);
                    if (info.signatures != null) {
                        msg = msg.concat("\nMD5：\n").concat(info.signatures[0].toCharsString());
                    }
                    builder.setMessage(msg);
                    builder.setPositiveButton("确定", (dialog, which) -> dialog.dismiss());
                    builder.setOnCancelListener(DialogInterface::dismiss);
                    builder.create().show();
                } else {
                    Toast.makeText(this, "包解析异常", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }

    /**
     * 启动第三方apk
     * <p>
     * 如果已经启动apk，则直接将apk从后台调到前台运行（类似home键之后再点击apk图标启动），如果未启动apk，则重新启动
     */

    public static Intent getAppOpenIntentByPackageName(Context context, String packageName) {
        String mainAct = null;
        PackageManager pkgMag = context.getPackageManager();
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_NEW_TASK);
//        @SuppressLint("WrongConstant")
        List<ResolveInfo> list = pkgMag.queryIntentActivities(intent, PackageManager.MATCH_ALL);
        // 获取指定应用程序activity的信息(按我的理解是：某一个应用程序的最后一个在前台出现过的activity。)
        //        ResolveInfo resolveInfo = pkgMag.resolveActivity(intent, 0);
        for (int i = 0; i < list.size(); i++) {
            ResolveInfo info = list.get(i);
            if (info.activityInfo.packageName.equals(packageName)) {
                mainAct = info.activityInfo.name;
                break;
            }
        }
        if (TextUtils.isEmpty(mainAct)) {
            return null;
        }
        intent.setComponent(new ComponentName(packageName, mainAct));
        return intent;
    }

    public static Intent getServiceOpenIntentByPackageName(Context context, String packageName) {
        String mainAct = null;
        PackageManager pkgMag = context.getPackageManager();
        Intent intent = new Intent();
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_NEW_TASK);
//        @SuppressLint("WrongConstant")
        List<ResolveInfo> list = pkgMag.queryIntentServices(intent, PackageManager.MATCH_DEFAULT_ONLY);
        // 获取指定应用程序activity的信息(按我的理解是：某一个应用程序的最后一个在前台出现过的activity。)
        //        ResolveInfo resolveInfo = pkgMag.resolveActivity(intent, 0);
        for (int i = 0; i < list.size(); i++) {
            ResolveInfo info = list.get(i);
            if (info.activityInfo.packageName.equals(packageName)) {
                mainAct = info.activityInfo.name;
                break;
            }
        }
        if (TextUtils.isEmpty(mainAct)) {
            return null;
        }
        intent.setComponent(new ComponentName(packageName, mainAct));
        return intent;
    }

    /**
     * 输出成功信息
     *
     * @param code
     */
    private void stdout(String code) {
        Toast.makeText(this, "已复制签名：" + code, Toast.LENGTH_LONG).show();
        copy(code);
        // 输出正确日志
        Log.d(TAG, "stdout() called with: " + "code = [" + code + "]");
    }

    /**
     * 输出错误信息
     *
     * @param reason
     */
    private void errout(String reason) {
        Toast.makeText(this, "获取失败：" + reason, Toast.LENGTH_LONG).show();
        // 输出错误日志
        Log.d(TAG, "errout() called with: " + "reason = [" + reason + "]");
    }

    /**
     * 复制内容到剪切板
     *
     * @param copyStr
     * @return
     */
    private boolean copy(String copyStr) {
        try {
            //获取剪贴板管理器
            ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
            // 创建普通字符型ClipData
            ClipData mClipData = ClipData.newPlainText("Label", copyStr);
            // 将ClipData内容放到系统剪贴板里。
            cm.setPrimaryClip(mClipData);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    private Signature[] getRawSignature(Context paramContext, String paramString) {
        if ((paramString == null) || (paramString.length() == 0)) {
            errout("获取签名失败，包名为 null");
            return null;
        }
        PackageManager localPackageManager = paramContext.getPackageManager();
        PackageInfo localPackageInfo;
        try {
            localPackageInfo = localPackageManager.getPackageInfo(paramString, PackageManager.GET_SIGNATURES);
            if (localPackageInfo == null) {
                errout("信息为 null, 包名 = " + paramString);
                return null;
            }
        } catch (PackageManager.NameNotFoundException localNameNotFoundException) {
            errout("包名没有找到...");
            return null;
        }
        return localPackageInfo.signatures;
    }

    /**
     * 开始获得签名
     *
     * @param packageName 报名
     * @return
     */
    private void getSign(String packageName) {
        Signature[] arrayOfSignature = getRawSignature(this, packageName);
        if ((arrayOfSignature == null) || (arrayOfSignature.length == 0)) {
            errout("signs is null");
            return;
        }

        stdout(Md5.getMessageDigest(arrayOfSignature[0].toByteArray()));
    }
}
